import java.io.File;

/**
 * Created with IntelliJ IDEA.
 * User: polly
 * Date: 12/2/13
 * Time: 2:54 PM
 * To change this template use File | Settings | File Templates.
 */
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.w3c.dom.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class XMLToExcel {
    private static HSSFWorkbook wb = new HSSFWorkbook();
    private static String fileNameToSearch = "testng-results.xml";
    private static String passed;
    private static String failed;
    private static String skipped;
    private static String total;
    private static String time;
    private static List<String> result = new ArrayList<String>();
    private static List<String> suiteNames = new ArrayList<String>();
    private static List<String> errorMessages = new ArrayList<String>();
    private static String slash = System.getProperty("file.separator");
    private static int totalPass;
    private static int totalFail;
    private static int totalSkipp;
    private static int totalTests;
    private static int totalTime = 0;
    private static HSSFSheet spreadSheet;

    public static String getFileNameToSearch() {
        return fileNameToSearch;
    }

    public static void setFileNameToSearch(String fileNameToSearch) {
        fileNameToSearch = fileNameToSearch;
    }

    public static List<String> getResult() {
        return result;
    }

    public static List<String> getFailedSuites() {
        return suiteNames;
    }

    public static List<String> getErrorMessages() {
        return errorMessages;
    }

    public static String PASSED() {
        return passed;
    }

    public static String FAILED() {
        return failed;
    }

    public static String SKIPPED() {
        return skipped;
    }

    public static String TOTAL() {
        return total;
    }

    public static String TOTAL_TIME() {
        return time;
    }

    public static void main(String[] args) throws ArrayIndexOutOfBoundsException{
        try {
            //check to see if the String array is empty
            String projectName = args[0];
            String resultPath = args[1];
            String fileOut = args[2];

            XMLToExcel excel = new XMLToExcel();
            excel.generateExcel(projectName, resultPath, fileOut);
        }
        catch (ArrayIndexOutOfBoundsException e){
            System.out.println("There were no commandline arguments passed! \nPlease specify all required arguments:");
            System.out.println("----------------------");
            System.out.println("*Project name");
            System.out.println("*Path to results");
            System.out.println("*Path to output File");
            System.out.println("----------------------");
            System.out.println("e.g. java -jar tng2xls.jar huita /home/results /home\nor\t" +
                    "java -jar tng2xls.jar hui \"C:\\\\Tests Results\" \"D:\\\\\"");
        }
    }

    public static void generateExcel(String fileName, String resultPath, String fileOut) {
        try {
            spreadSheet = wb.createSheet("TotalResults");
            spreadSheet.setColumnWidth(0, (300 * 35));

            HSSFRow row = spreadSheet.createRow(5);
            row.setHeight((short)400);

            HSSFCell cell = row.createCell(0);
            cell.setCellValue("Test Suite");
            cell.setCellStyle(bottomStyle());
            cell = row.createCell(1);
            cell.setCellValue("Total");
            cell.setCellStyle(bottomStyle());
            cell = row.createCell(2);
            cell.setCellValue("Passed");
            cell.setCellStyle(bottomStyle());
            cell = row.createCell(3);
            cell.setCellValue("Failed");
            cell.setCellStyle(bottomStyle());
            cell = row.createCell(4);
            cell.setCellValue("Skipped");
            cell.setCellStyle(bottomStyle());
            cell = row.createCell(5);
            cell.setCellValue("Run Time");
            cell.setCellStyle(bottomStyle());

            searchDirectory(new File(resultPath));
            for (int i=0 ; i<getResult().size(); i++){
                File res = new File(getResult().get(i));
                parseXML(res);
                String name = res.getParent().toString();
                HSSFRow row_suites = spreadSheet.createRow(i+6);
                row_suites.setHeight((short)400);
                cell = row_suites.createCell(0);
                cell.setCellStyle(listStyle());
                cell.setCellValue(name.substring(name.lastIndexOf(slash) + 1));
                cell = row_suites.createCell(1);
                cell.setCellValue(TOTAL());
                cell.setCellStyle(tableStyle());
                cell = row_suites.createCell(2);
                cell.setCellValue(PASSED());
                cell.setCellStyle(tableStyle());cell = row_suites.createCell(3);
                cell.setCellValue(FAILED());
                if (Integer.valueOf(PASSED()) < Integer.valueOf(FAILED())){
                    cell.setCellStyle(failedCell());
                } else cell.setCellStyle(tableStyle());
                cell = row_suites.createCell(4);
                cell.setCellValue(SKIPPED());
                cell.setCellStyle(tableStyle());
                cell = row_suites.createCell(5);
                cell.setCellValue(convertTime(Integer.valueOf(TOTAL_TIME())));
                if (Integer.valueOf(TOTAL_TIME()) > 3600000){
                    cell.setCellStyle(failedCell());
                } else cell.setCellStyle(tableStyle());
                System.out.println("----------------------------");
                System.out.println("Suite Name: " + name.substring(name.lastIndexOf(slash) + 1));
                System.out.println("TESTS PASSED: " + PASSED());
                totalPass = totalPass + Integer.valueOf(PASSED());
                System.out.println("TESTS FAILED: " + FAILED());
                totalFail = totalFail + Integer.valueOf(FAILED());
                System.out.println("TESTS SKIPPED: " + SKIPPED());
                totalSkipp = totalSkipp + Integer.valueOf(SKIPPED());
                System.out.println("TOTAL SKIPPED: " + TOTAL());
                totalTests = totalTests + Integer.valueOf(TOTAL());
                System.out.println("Run Time: " + convertTime(Integer.valueOf(TOTAL_TIME())));
                totalTime = totalTime + Integer.valueOf(TOTAL_TIME());
                if(Integer.valueOf(FAILED())!=0){
                    createFailedTab(res, name.substring(name.lastIndexOf(slash) + 1));
                }
            }
            createHeader();
            HSSFRow row_total = spreadSheet.createRow(getResult().size()+6);
            row_total.setHeight((short)400);
            HSSFCell cell_total = row_total.createCell(0);
            cell_total.setCellStyle(bottomStyle());
            cell_total.setCellValue("Total Results: ");
            cell_total = row_total.createCell(1);
            cell_total.setCellValue(totalTests);
            cell_total.setCellStyle(bottomStyle());
            cell_total = row_total.createCell(2);
            cell_total.setCellValue(totalPass);
            cell_total.setCellStyle(passedCell());
            cell_total = row_total.createCell(3);
            cell_total.setCellValue(totalFail);
            cell_total.setCellStyle(failedCell());
            cell_total = row_total.createCell(4);
            cell_total.setCellValue(totalSkipp);
            cell_total.setCellStyle(skippedCell());
            cell_total = row_total.createCell(5);
            cell_total.setCellValue(convertTime(Integer.valueOf(totalTime)));
            cell_total.setCellStyle(bottomStyle());
            // Outputting to Excel spreadsheet
            FileOutputStream output = new FileOutputStream(new File(fileOut + slash + fileName + ".xls"));
            wb.write(output);
            output.flush();
            output.close();
        } catch (Throwable e) {
            System.out.println("IOException " + e.getMessage());
        }
    }

    public static void searchDirectory(File directory) {

        setFileNameToSearch(fileNameToSearch);

        if (directory.isDirectory()) {
            suiteNames(directory);
        } else {
            System.out.println(directory.getAbsoluteFile() + " is not a directory!");
        }

    }

    private static void suiteNames(File file) {

        if (file.isDirectory()) {
            if (file.canRead()) {
                for (File temp : file.listFiles()) {
                    if (temp.isDirectory()) {
                        suiteNames(temp);
                    } else {
                        if (getFileNameToSearch().equals(temp.getName().toLowerCase())) {
                            result.add(temp.getAbsoluteFile().toString());
                        }
                    }
                }

            } else {
                System.out.println(file.getAbsoluteFile() + "Permission Denied");
            }
        }
    }

    private static void parseXML(File file){
        try {

            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);

            doc.getDocumentElement().normalize();

            doc.getDocumentElement().normalize();
            Node item = doc.getChildNodes().item(0);
            Node pNode = item.getAttributes().getNamedItem("passed");
            passed = pNode.getNodeValue();
            Node fNode = item.getAttributes().getNamedItem("failed");
            failed = fNode.getNodeValue();
            Node sNode = item.getAttributes().getNamedItem("skipped");
            skipped = sNode.getNodeValue();
            Node tNode = item.getAttributes().getNamedItem("total");
            total = tNode.getNodeValue();

            NodeList nList = doc.getElementsByTagName("suite");

            for (int temp = 0; temp < nList.getLength(); temp++) {

                Node nNode = nList.item(temp);

                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) nNode;
                    time=eElement.getAttribute("duration-ms");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String convertTime (long millis){
        return String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
                TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
    }

    private static void failedResults(File file){
        try{
            suiteNames.clear();
            errorMessages.clear();
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);
            NodeList methods = doc.getElementsByTagName("message");

            for (int i = 0; i < methods.getLength(); i++) {
                NamedNodeMap attrs = methods.item(i).getParentNode().getParentNode().getAttributes();
                suiteNames.add(attrs.getNamedItem("name").getNodeValue().toString());
                errorMessages.add(methods.item(i).getFirstChild().getNextSibling().getNodeValue());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void createFailedTab(File resultFile, String tabName){
        failedResults(resultFile);
        HSSFSheet spreadSheet_suite = wb.createSheet(tabName);
        HSSFRow row_suite = spreadSheet_suite.createRow(0);
//        spreadSheet_suite.setColumnWidth(0, (300 * 25));
        row_suite.setHeight((short)400);

        HSSFCell cell_suite = row_suite.createCell(0);
        cell_suite.setCellValue("Test Case ID");
        cell_suite.setCellStyle(bottomStyle());
        cell_suite = row_suite.createCell(1);
        cell_suite.setCellValue("Exception Message");
        cell_suite.setCellStyle(bottomStyle());
        for(int s =0; s<getFailedSuites().size(); s++){
            for(int f =0; f<getErrorMessages().size(); f++){
                HSSFRow row_failed = spreadSheet_suite.createRow(s+1);
                row_failed.setHeight((short)6000);
                HSSFCell cell_failed = row_failed.createCell(0);
                cell_failed.setCellValue(getFailedSuites().get(s));
                cell_failed.setCellStyle(listStyle());
                cell_failed = row_failed.createCell(1);
                cell_failed.setCellValue(getErrorMessages().get(f));
                cell_failed.setCellStyle(listStyle());
            }
        }
        spreadSheet_suite.autoSizeColumn(0);
        spreadSheet_suite.autoSizeColumn(1);
    }

    private static HSSFCellStyle mainStyle(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short) 12);
        font.setItalic(true);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
        topStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_CENTER);
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        topStyle.setFont(font);
        return topStyle;
    }

    private static HSSFCellStyle listStyle(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)12);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_TOP);
        topStyle.setFont(font);
        return topStyle;
    }

    private static HSSFCellStyle tableStyle(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)12);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_CENTER);
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        topStyle.setFont(font);
        topStyle.setWrapText(true);
        return topStyle;
    }

    private static HSSFCellStyle bottomStyle(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)12);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        topStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        topStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_CENTER);
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        topStyle.setFont(font);
        return topStyle;
    }

    private static HSSFCellStyle failedCell(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)12);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
        topStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        topStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_CENTER);
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        topStyle.setFont(font);
        return topStyle;
    }

    private static HSSFCellStyle passedCell(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)12);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
        topStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        topStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_CENTER);
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        topStyle.setFont(font);
        return topStyle;
    }

    private static HSSFCellStyle skippedCell(){
        HSSFFont font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)12);
        HSSFCellStyle topStyle =wb.createCellStyle();
        topStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
        topStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        topStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        topStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        topStyle.setAlignment(CellStyle.VERTICAL_CENTER);
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        topStyle.setFont(font);
        return topStyle;
    }

    private static void createHeader(){
        HSSFRow row_stat = spreadSheet.createRow(0);
        row_stat.setHeight((short)400);
        HSSFCell cell_stat = row_stat.createCell(0);
        cell_stat.setCellStyle(mainStyle());
        cell_stat.setCellValue("TESTS STATISTIC");
        spreadSheet.addMergedRegion(CellRangeAddress.valueOf("A1:F1"));
        HSSFRow row_total_res = spreadSheet.createRow(1);
        row_total_res.setHeight((short)400);
        HSSFCell cell_total_res = row_total_res.createCell(0);
        cell_total_res.setCellStyle(mainStyle());
        cell_total_res.setCellValue("Total tests: " + totalTests);
        spreadSheet.addMergedRegion(CellRangeAddress.valueOf("A2:F2"));
        HSSFRow row_total_p = spreadSheet.createRow(2);
        row_total_p.setHeight((short)400);
        HSSFCell cell_total_p = row_total_p.createCell(0);
        cell_total_p.setCellStyle(mainStyle());
        cell_total_p.setCellValue("Passed tests: " + totalPass);
        spreadSheet.addMergedRegion(CellRangeAddress.valueOf("A3:F3"));
        HSSFRow row_total_f = spreadSheet.createRow(3);
        row_total_f.setHeight((short)400);
        HSSFCell cell_total_f = row_total_f.createCell(0);
        cell_total_f.setCellStyle(mainStyle());
        cell_total_f.setCellValue("Failed tests: " + totalFail);
        spreadSheet.addMergedRegion(CellRangeAddress.valueOf("A4:F4"));
        HSSFRow row_total_s = spreadSheet.createRow(4);
        row_total_s.setHeight((short)400);
        HSSFCell cell_total_s = row_total_s.createCell(0);
        cell_total_s.setCellStyle(mainStyle());
        cell_total_s.setCellValue("Skipped tests: " + totalSkipp);
        spreadSheet.addMergedRegion(CellRangeAddress.valueOf("A5:F5"));
    }
}